package cn.slipi.common.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@EnableAsync
@Configuration
public class AsyncConfiguration {

    @Bean(name = "ScThreadPoolTaskExecutor")
    public ThreadPoolTaskExecutor getAsyncTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数
        threadPoolTaskExecutor.setCorePoolSize(10);
        //线程池维护的最大线程数，只有队列满了之后才会申请超过核心线程并且小于最大线程的线程取执行任务
        threadPoolTaskExecutor.setMaxPoolSize(100);
        //队列容量
        threadPoolTaskExecutor.setQueueCapacity(50);
        //超过核心线程的线程处于空闲状态的存活时间
        threadPoolTaskExecutor.setKeepAliveSeconds(200);
        //创建的线程前缀名
        threadPoolTaskExecutor.setThreadNamePrefix("sc-");
        /**
         * 当新任务到来，核心线程已经全部在处理任务，并且任务等待队列已满，并且任务已经等于线程池最大线程数，那么将使用拒绝策略来处理新任务。
         * 通常有以下四种策略：
         * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
         * ThreadPoolExecutor.DiscardPolicy：也是丢弃任务，但是不抛出异常。
         * ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
         * ThreadPoolExecutor.CallerRunsPolicy：重试添加当前的任务，自动重复调用 execute() 方法，直到成功
         */
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }

}
